package net.kong.sns.rest.client.method;

import java.util.Map;
import net.kong.sns.rest.client.ApiError;
import net.kong.sns.rest.client.ErrorResponse;
import net.kong.sns.rest.client.ErrorResponseException;
import net.kong.sns.rest.client.ErrorResponseImpl;
import net.kong.sns.rest.client.InvalidResponseException;
import net.kong.sns.rest.client.KongApiMethod;
import net.kong.sns.rest.client.rest.HttpResponseContent;
import net.kong.org.stringtree.json.ExceptionErrorListener;
import net.kong.org.stringtree.json.JSONReader;
import net.kong.org.stringtree.json.JSONValidatingReader;

/**
 * @author <a href="mailto:lanhuai@gmail.com">Ning Yubin</a>
 * @version $Id: JsonMethodInvokeBase.java,v 1.6.2.1 2009/12/21 09:38:30 wangyuanming Exp $
 */
public abstract class JsonMethodInvokeBase<T> extends MethodInvokeBase<T> {

    protected JSONReader reader;

    protected JsonMethodInvokeBase(KongApiMethod method, String sessionKey) {
        super(method, ResponseFormat.JSON, sessionKey);
        this.reader = new JSONValidatingReader(new ExceptionErrorListener());
    }

    protected JsonMethodInvokeBase(KongApiMethod method) {
        super(method, ResponseFormat.JSON);
        this.reader = new JSONValidatingReader(new ExceptionErrorListener());
    }

    protected abstract T processJsonResponse(HttpResponseContent responseData) throws InvalidResponseException;

    @Override
    public T parseResponse(HttpResponseContent responseData) throws ApiError {
        if (isErrorResponse(responseData)) {
            ErrorResponse errorResponse = processErrorResponse(responseData);
            throw new ErrorResponseException(errorResponse);
        }
        return processJsonResponse(responseData);
    }

    @Override
    public boolean isErrorResponse(HttpResponseContent responseData) {
        int status = responseData.getHttpStatus().value();
        return status >= 500;
    }

    @Override
    public ErrorResponse processErrorResponse(HttpResponseContent responseData) {
        int status = responseData.getHttpStatus().value();
        String response = responseData.getBody();
        Map<String, Object> errorMap = (Map<String, Object>) this.reader.read(response);
        return new ErrorResponseImpl(((Number) errorMap.get("error_code")).intValue(), errorMap.get("error_constant").toString(), errorMap
                .get("error_msg").toString());
    }
}
